package com.dongrj.framework.web.utils;

import com.dongrj.framework.core.exception.Assert;
import com.dongrj.framework.core.exception.BusinessException;
import com.dongrj.framework.core.exception.SystemException;
import com.dongrj.framework.core.utils.JsonUtils;
import com.dongrj.framework.core.utils.ObjectUtils;
import com.dongrj.framework.web.HttpCallBack;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;

/**
 * @author dongrongjun
 * @date 2020/06/01
 */
@Slf4j
public class RestTemplateUtils {

    private static RestTemplate restTemplate;

    /**
     * RestTemplate GET请求
     *
     * @param url    url
     * @param logger 日志记录
     */
    public static MarketResponseEntity<String> get(String url, Map<String, ?> params, Logger logger) {
        if (params != null && params.size() > 0) {
            Map<String, Object> map = removeNullValue(params);
            String paramStr = Joiner.on("&").withKeyValueSeparator("=").join(map);
            url = url + "?" + paramStr;
        }
        logger.info("get.url={}", url);
        MarketResponseEntity<String> marketResponseEntity = new MarketResponseEntity<>(url);
        try {
            ResponseEntity<String> forEntity = getRestTemplate().getForEntity(url, String.class);
            marketResponseEntity.setResponseEntity(forEntity);
        } catch (Exception e) {
            marketResponseEntity.setError(true);
            marketResponseEntity.setException(e);
            logger.error("RestTemplate GET请求错误:" + url, e);
        }
        return marketResponseEntity;
    }

    /**
     * Application/Json封装
     *
     * @param url   请求地址
     * @param param 参数
     */
    public static MarketResponseEntity<String> post(String url, Object param, Logger logger) {
        String paramJson = JsonUtils.toJson(param);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> entity = new HttpEntity<>(paramJson, headers);
        MarketResponseEntity<String> marketResponseEntity = new MarketResponseEntity<>(url, paramJson);
        try {
            ResponseEntity<String> post = getRestTemplate().postForEntity(url, entity, String.class);
            marketResponseEntity.setResponseEntity(post);
            return marketResponseEntity;
        } catch (Exception e) {
            marketResponseEntity.setError(true);
            marketResponseEntity.setException(e);
            String format = String.format("post.param=%s,url=%s", paramJson, url);
            logger.error(format, e);
        }
        return marketResponseEntity;
    }


    /**
     * Application/Json封装
     *
     * @param url         请求地址
     * @param param       参数
     * @param successFunc 判断成功的函数
     * @param callBack    回调
     * @param logger      日志记录器
     */
    public static MarketResponseEntity<String> post(String url, Object param, Function<MarketResponseEntity<String>, Boolean> successFunc, HttpCallBack callBack, Logger logger) {
        String paramJson = JsonUtils.toJson(param);
        MarketResponseEntity<String> marketResponseEntity = new MarketResponseEntity<>(url, paramJson);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> entity = new HttpEntity<>(paramJson, headers);
        try {
            ResponseEntity<String> post = getRestTemplate().postForEntity(url, entity, String.class);
            marketResponseEntity.setResponseEntity(post);
            if (callBack != null) {
                if (successFunc != null) {
                    Boolean apply = successFunc.apply(marketResponseEntity);
                    if (apply) {
                        callBack.success(marketResponseEntity);
                    } else {
                        marketResponseEntity.setError(false);
                        callBack.fail(marketResponseEntity);
                    }
                } else {
                    callBack.success(marketResponseEntity);
                }
            }
            return marketResponseEntity;
        } catch (Exception e) {
            // 排除自定义的业务异常和系统异常
            if (e instanceof BusinessException || e instanceof SystemException) {
                throw e;
            }
            marketResponseEntity.setError(false);
            String format = String.format("post.param=%s,url=%s", paramJson, url);
            logger.error(format, e);
            if (callBack != null) {
                callBack.exception(marketResponseEntity, e);
            }
        }
        return marketResponseEntity;
    }


    /**
     * HttpCode=200处理方法
     *
     * @param acoResponseEntity Http请求结果
     * @param successCodeKey    成功标识Key
     * @param successCodeValue  成功标志值
     * @param errorMsgKey       错误信息Key
     * @param errorFunction     错误处理函数
     * @param log               日志记录器
     */
    public static MarketBody body(MarketResponseEntity<String> acoResponseEntity, String successCodeKey, String successCodeValue, String errorMsgKey, Function<String, String> errorFunction, Logger log) {
        ResponseEntity<String> responseEntity = acoResponseEntity.getResponseEntity();
        String body = responseEntity.getBody();
        String codeValue = JsonUtils.getValue(body, successCodeKey);
        MarketBody acoBody = new MarketBody();
        if (Objects.equals(codeValue, successCodeValue)) {
            acoBody.setBody(body);
            return acoBody;
        } else {
            acoBody.setError(true);
            if (errorFunction != null) {
                String throwMsg = errorFunction.apply(codeValue);
                acoBody.setErrorMsg(throwMsg);
            } else {
                String msgValue = JsonUtils.getValue(body, errorMsgKey);
                acoBody.setErrorMsg(msgValue);
            }
        }
        log.error("body.acoBody={}", acoBody);
        return acoBody;
    }


    /**
     * 手动返回Json数据
     */
    public static void response(HttpServletResponse response, String resultJson) throws IOException {
        response.setContentType("application/json;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        PrintWriter pw = response.getWriter();
        pw.write(resultJson);
    }

    /**
     * 去除参数种的null值
     *
     * @param params 参数
     */
    public static Map<String, Object>

    removeNullValue(Map<String, ?> params) {
        Map<String, Object> stringMap = new HashMap<>(params.size());
        for (Map.Entry<String, ?> entry : params.entrySet()) {
            Object value = entry.getValue();
            if (ObjectUtils.isNotEmpty(value)) {
                stringMap.put(entry.getKey(), entry.getValue());
            }
        }
        return stringMap;
    }

    /**
     * @param baseUrl url
     * @param k1      键1
     * @param v1      值1
     */
    public static String paramUrl(String baseUrl, String k1, String v1) {
        return baseUrl + "?" + Joiner.on("&").withKeyValueSeparator("=").join(ImmutableMap.of(k1, v1));
    }

    /**
     * @param baseUrl url
     * @param k1      键1
     * @param v1      值1
     * @param k2      键2
     * @param v2      值2
     */
    public static String paramUrl(String baseUrl, String k1, String v1, String k2, String v2) {
        return baseUrl + "?" + Joiner.on("&").withKeyValueSeparator("=").join(ImmutableMap.of(k1, v1, k2, v2));
    }


    /**
     * @param baseUrl url
     * @param k1      键1
     * @param v1      值1
     * @param k2      键2
     * @param v2      值2
     * @param k3      键1
     * @param v3      值1
     */
    public static String paramUrl(String baseUrl, String k1, String v1, String k2, String v2, String k3, String v3) {
        return baseUrl + "?" + Joiner.on("&").withKeyValueSeparator("=").join(ImmutableMap.of(k1, v1, k2, v2, k3, v3));
    }

    /**
     * @param baseUrl url
     * @param k1      键1
     * @param v1      值1
     * @param k2      键2
     * @param v2      值2
     * @param k3      键1
     * @param v3      值1
     * @param k4      键2
     * @param v4      值2
     */
    public static String paramUrl(String baseUrl, String k1, String v1, String k2, String v2, String k3, String v3, String k4, String v4) {
        return baseUrl + "?" + Joiner.on("&").withKeyValueSeparator("=").join(ImmutableMap.of(k1, v1, k2, v2, k3, v3, k4, v4));
    }

    /**
     * @param baseUrl url
     * @param k1      键1
     * @param v1      值1
     * @param k2      键2
     * @param v2      值2
     * @param k3      键3
     * @param v3      值3
     * @param k4      键4
     * @param v4      值4
     * @param k5      键5
     * @param v5      值5
     */
    public static String paramUrl(String baseUrl, String k1, String v1, String k2, String v2, String k3, String v3, String k4, String v4, String k5, String v5) {
        return baseUrl + "?" + Joiner.on("&").withKeyValueSeparator("=").join(ImmutableMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5));
    }


    public static void setRestTemplate(RestTemplate template) {
        if (Objects.isNull(RestTemplateUtils.restTemplate)) {
            if (Objects.nonNull(template)) {
                RestTemplateUtils.restTemplate = template;
            } else {
                Assert.throwSys("RestTemplate不能为空!");
            }
        }
    }

    public static RestTemplate getRestTemplate() {
        if (restTemplate == null) {
            restTemplate = SpringUtils.getBean(RestTemplate.class);
            Assert.notEmpty(restTemplate, "RestTemplate没有集成!");
        }
        return restTemplate;
    }

}
